package com.tan.mypark.manager;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkRequest;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.reactivex.disposables.Disposable;
import ua.naiksoftware.stomp.Stomp;
import ua.naiksoftware.stomp.StompClient;
import ua.naiksoftware.stomp.dto.StompHeader;


public class WebSocketManager {
    private static final String TAG = "WebSocketManager";
    private final Context context;
    private final String wsUrl;
    private final String authToken;
    private StompClient stompClient;
    private OnMessageReceivedListener listener;
    private boolean isConnected;
    private boolean isManualDisconnect = false;
    private Handler reconnectHandler;
    private int reconnectAttempts = 0;
    private static final long MAX_RECONNECT_DELAY = 30000;
    private static final long HEART_BEAT_INTERVAL = 15000;

    private Map<String, Disposable> topicDisposables = new HashMap<>();
    private Map<String, String> connectHeaders = new HashMap<>(); // 保持成员变量

    public boolean isConnected() {
        return isConnected;
    }

    public interface OnMessageReceivedListener {
        void onMessage(String topic, String message);
        void onConnectStatusChanged(boolean isConnected);
        void onError(Throwable throwable);
    }

    public WebSocketManager(Context context, String wsUrl, String authToken) {
        this.context = context.getApplicationContext();
        this.wsUrl = wsUrl;
        this.authToken = authToken;
        this.stompClient = Stomp.over(Stomp.ConnectionProvider.OKHTTP, wsUrl);
        this.reconnectHandler = new Handler(Looper.getMainLooper());
        initStompClient();
        registerNetworkCallback();
    }

    public void setOnMessageReceivedListener(OnMessageReceivedListener listener) {
        this.listener = listener;
    }

    private void initStompClient() {
        // 初始化连接参数（仅调用一次，但保留参数）
        updateConnectHeaders(); // 提取为独立方法，方便重连时更新

        stompClient.withClientHeartbeat(Math.toIntExact(HEART_BEAT_INTERVAL))
                .withServerHeartbeat(Math.toIntExact(HEART_BEAT_INTERVAL));

        stompClient.lifecycle().subscribe(lifecycleEvent -> {
            switch (lifecycleEvent.getType()) {
                case OPENED:
                    Log.d(TAG, "WebSocket连接成功: " + wsUrl);
                    isConnected = true;
                    reconnectAttempts = 0;
                    if (listener != null) {
                        listener.onConnectStatusChanged(true);
                    }
                    break;
                case ERROR:
                    Log.e(TAG, "WebSocket连接错误: " + lifecycleEvent.getException());
                    if (listener != null) {
                        listener.onError(lifecycleEvent.getException());
                    }
                    handleDisconnect();
                    break;
                case CLOSED:
                    Log.d(TAG, "WebSocket已关闭: " + wsUrl);
                    handleDisconnect();
                    break;
            }
        }, throwable -> {
            Log.e(TAG, "生命周期监听错误", throwable);
            if (listener != null) {
                listener.onError(throwable);
            }
        });
    }

    /**
     * 新增：更新连接参数（可在重连前调用，确保参数有效）
     */
    private void updateConnectHeaders () {
        connectHeaders.clear (); // 先清空旧值，避免重复
        connectHeaders.put ("heart-beat", HEART_BEAT_INTERVAL + "," + HEART_BEAT_INTERVAL);
        if (authToken != null && !authToken.isEmpty ()) {
            connectHeaders.put ("Authorization", "Bearer" + authToken);
        }
    }

    private List<StompHeader> convertMapToStompHeaders(Map<String, String> headerMap) {
        List<StompHeader> stompHeaders = new ArrayList<>();
        for (Map.Entry<String, String> entry : headerMap.entrySet ()) {
// 每个 Map 键值对，对应一个 StompHeader 对象
            stompHeaders.add (new StompHeader (entry.getKey (), entry.getValue ()));
        }
        return stompHeaders;
    }

    private void handleDisconnect() {
        if (isConnected) {
            isConnected = false;
            reconnectAttempts++; // 修复：每次断开递增重连次数
            if (listener != null) {
                listener.onConnectStatusChanged(false);
            }
            scheduleReconnect();
        }
    }

    public void resetManualDisconnect() {
        isManualDisconnect = false;
    }

    private void scheduleReconnect() {
        // 修复：重连前重置手动断开标记（仅手动调用disconnect()时才为true）
        isManualDisconnect = false;
        if (isManualDisconnect) {
            Log.d(TAG, "手动断开连接，不进行自动重连");
            return;
        }

        // 修复：限制reconnectAttempts最大为10（避免2^10=1024秒，超过MAX_RECONNECT_DELAY）
        int attempts = Math.min(reconnectAttempts, 10);
        long delay = (long) Math.min(Math.pow(2, attempts) * 1000, MAX_RECONNECT_DELAY);
        Log.d(TAG, "计划" + delay/1000 + "秒后重连（第" + (attempts+1) + "次）: " + wsUrl);

        reconnectHandler.postDelayed(() -> {
            reconnectAttempts++;
            connect(); // 执行重连
        }, delay);
    }

    /**
     * 连接WebSocket（重连时确保参数有效）
     */
//    public void connect() {
//        if (isConnected) {
//            Log.d(TAG, "WebSocket已连接，无需重复连接: " + wsUrl);
//            return;
//        }
//
//        if (!isNetworkAvailable()) {
//            Log.e(TAG, "网络不可用，无法连接WebSocket");
//            if (listener != null) {
//                listener.onError(new Exception("网络不可用"));
//            }
//            scheduleReconnect();
//            return;
//        }
//
//        // 重连前更新参数（防止Token过期等场景）
//        updateConnectHeaders();
//        Log.d(TAG, "正在连接WebSocket: " + wsUrl);
//        List<StompHeader> stompHeaders = convertMapToStompHeaders (connectHeaders); // 转换格式
//        stompClient.connect(stompHeaders); // 显式传入headers（关键修改）
//    }
    public void connect() {
        if (isConnected) {
            Log.d(TAG, "WebSocket已连接，无需重复连接: " + wsUrl);
            return;
        }

        // 修复：销毁旧实例，避免状态污染
        if (stompClient != null) {
            stompClient.disconnect();
            stompClient = null;
        }
        // 重建StompClient实例
        stompClient = Stomp.over(Stomp.ConnectionProvider.OKHTTP, wsUrl);
        initStompClient(); // 重新初始化客户端（包括生命周期监听）

        // 检查网络状态
        if (!isNetworkAvailable()) {
            Log.e(TAG, "网络不可用，无法连接WebSocket");
            if (listener != null) {
                listener.onError(new Exception("网络不可用"));
            }
            scheduleReconnect();
            return;
        }

        Log.d(TAG, "正在连接WebSocket: " + wsUrl);
        List<StompHeader> stompHeaders = convertMapToStompHeaders (connectHeaders); // 转换格式
        stompClient.connect(stompHeaders); // 显式传入headers（关键修改）
    }

    /**
     * 断开WebSocket连接（移除clear()）
     */
    public void disconnect() {
        Log.d(TAG, "手动断开WebSocket连接: " + wsUrl);
        isManualDisconnect = true;
        reconnectHandler.removeCallbacksAndMessages(null);
        unsubscribeAll();
        // 移除 connectHeaders.clear()，保留参数供下次连接使用
        if (stompClient != null) {
            stompClient.disconnect();
        }
        isConnected = false;
        if (listener != null) {
            listener.onConnectStatusChanged(false);
        }
    }

    public void subscribe(String topic) {
        if (!isConnected) {
            Log.e(TAG, "无法订阅主题 " + topic + ": WebSocket未连接");
            return;
        }

        if (topicDisposables.containsKey(topic)) {
            Log.d(TAG, "主题 " + topic + " 已订阅，无需重复订阅");
            return;
        }

        Log.d(TAG, "订阅主题: " + topic);
        Disposable disposable = stompClient.topic(topic)
                .subscribe(
                        topicMessage -> {
                            if (listener != null) {
                                listener.onMessage(topic, topicMessage.getPayload());
                            }
                        },
                        throwable -> {
                            Log.e(TAG, "订阅主题失败: " + topic, throwable);
                            if (listener != null) {
                                listener.onError(throwable);
                            }
                        }
                );
        topicDisposables.put(topic, disposable);
    }

    public void unsubscribe(String topic) {
        Disposable disposable = topicDisposables.get(topic);
        if (disposable != null && !disposable.isDisposed()) {
            disposable.dispose();
            topicDisposables.remove(topic);
            Log.d(TAG, "取消订阅主题: " + topic);
        }
    }

    public void unsubscribeAll() {
        for (Disposable disposable : topicDisposables.values()) {
            if (!disposable.isDisposed()) {
                disposable.dispose();
            }
        }
        topicDisposables.clear();
        Log.d(TAG, "取消所有主题订阅");
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) return false;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return cm.getActiveNetwork() != null;
        } else {
            android.net.NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
            return activeNetworkInfo != null && activeNetworkInfo.isConnected();
        }
    }

    private void registerNetworkCallback() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            return;
        }

        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm == null) return;

        NetworkRequest request = new NetworkRequest.Builder().build();
        cm.registerNetworkCallback(request, new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                super.onAvailable(network);
                if (!isConnected && !isManualDisconnect) {
                    Log.d(TAG, "网络恢复，触发重连");
                    reconnectHandler.post(() -> connect());
                }
            }

            @Override
            public void onLost(Network network) {
                super.onLost(network);
                Log.d(TAG, "网络连接丢失");
                handleDisconnect();
            }
        });
    }

    public void release() {
//        disconnect();
//        reconnectHandler.removeCallbacksAndMessages(null);
//        topicDisposables.clear();
//        stompClient = null;
//        listener = null;
        disconnect();
        if (reconnectHandler != null) {
            reconnectHandler.removeCallbacksAndMessages(null);
            reconnectHandler = null;
        }
        topicDisposables.clear();
        stompClient = null;
        listener = null;
        connectHeaders.clear(); // 清空header
    }
}

//package com.tan.faceoffline.manager;
//
//import android.content.Context;
//import android.os.Handler;
//import android.os.Looper;
//import android.util.Log;
//
//import java.util.HashMap;
//import java.util.Map;
//import java.util.concurrent.TimeUnit;
//
//import ua.naiksoftware.stomp.Stomp;
//import ua.naiksoftware.stomp.StompClient;
//import ua.naiksoftware.stomp.dto.LifecycleEvent;
//import ua.naiksoftware.stomp.dto.StompHeader;
//
//public class WebSocketManager {
//    private static final String TAG = "WebSocketManager";
//    private final Context context;
//    private final String wsUrl;
//    private StompClient stompClient;
//    private OnMessageReceivedListener listener;
//    private boolean isConnected;
//    private boolean isManualDisconnect = false;//标记是否为手动断开（用于禁止自动重连）
//    private Handler reconnectHandler;
//    private static final long RECONNECT_DELAY = 5000; // 5秒后重试
//    private static final long HEART_BEAT_INTERVAL = 15000; // 15秒心跳间隔
//
//    public interface OnMessageReceivedListener {
//        void onMessage(String topic, String message);
//        void onConnectStatusChanged(boolean isConnected);
//    }
//
//    public WebSocketManager(Context context, String wsUrl) {
//        this.context = context;
//        this.wsUrl = wsUrl;
//        this.stompClient = Stomp.over(Stomp.ConnectionProvider.OKHTTP, wsUrl);
//        this.reconnectHandler = new Handler(Looper.getMainLooper());
//        initStompClient();
//    }
//
//    public void setOnMessageReceivedListener(OnMessageReceivedListener listener) {
//        this.listener = listener;
//    }
//
//    private void initStompClient() {
//        // 设置心跳参数（客户端每15秒发送一次，期望服务器每15秒发送一次）
//        Map<String, String> connectHeaders = new HashMap<>();
//        connectHeaders.put("heart-beat", HEART_BEAT_INTERVAL + "," + HEART_BEAT_INTERVAL);
//
//        // 配置Stomp客户端
//        stompClient.withClientHeartbeat(Math.toIntExact(HEART_BEAT_INTERVAL))
//                .withServerHeartbeat(Math.toIntExact(HEART_BEAT_INTERVAL));
//
//        // 监听连接生命周期
//        stompClient.lifecycle().subscribe(lifecycleEvent -> {
//            switch (lifecycleEvent.getType()) {
//                case OPENED:
//                    Log.d(TAG, "WebSocket连接成功: " + wsUrl);
//                    isConnected = true;
//                    if (listener != null) {
//                        listener.onConnectStatusChanged(true);
//                    }
//                    break;
//                case ERROR:
//                    Log.e(TAG, "WebSocket连接错误: " + lifecycleEvent.getException());
//                    handleDisconnect();
//                    break;
//                case CLOSED:
//                    Log.d(TAG, "WebSocket已关闭: " + wsUrl);
//                    handleDisconnect();
//                    break;
//            }
//        });
//    }
//
//    private void handleDisconnect() {
//        if (isConnected) {
//            isConnected = false;
//            if (listener != null) {
//                listener.onConnectStatusChanged(false);
//            }
//            scheduleReconnect();
//        }
//    }
//
//    //SpeechRecognitionActivity测试所用
////    private void handleDisconnect() {
////        if (isConnected) {
////            isConnected = false;
////            if (listener != null) {
////                listener.onConnectStatusChanged(false);
////            }
////            // 只有非手动断开时才触发重连
////            if (!isManualDisconnect) {
////                scheduleReconnect();
////            }
////        }
////    }
//
//    public void resetManualDisconnect() {
//        isManualDisconnect = false;
//    }
//
//    private void scheduleReconnect() {
//        Log.d(TAG, "计划" + RECONNECT_DELAY/1000 + "秒后重连WebSocket: " + wsUrl);
//        reconnectHandler.postDelayed(this::connect, RECONNECT_DELAY);
//    }
//
//    public void connect() {
//        if (isConnected) {
//            Log.d(TAG, "WebSocket已连接，无需重复连接: " + wsUrl);
//            return;
//        }
//
//        Log.d(TAG, "正在连接WebSocket: " + wsUrl);
//        stompClient.connect();
//    }
//
//    public void disconnect() {
//        Log.d(TAG, "手动断开WebSocket连接: " + wsUrl);
//        reconnectHandler.removeCallbacksAndMessages(null); // 取消重连计划
//        if (stompClient != null) {
//            stompClient.disconnect();
//        }
//        isConnected = false;
//        if (listener != null) {
//            listener.onConnectStatusChanged(false);
//        }
//    }
//
//    //SpeechRecognitionActivity测试所用
////    public void disconnect() {
////        Log.d(TAG, "手动断开WebSocket连接: " + wsUrl);
////        isManualDisconnect = true; // 标记为手动断开
////        reconnectHandler.removeCallbacksAndMessages(null); // 彻底取消所有重连任务
////        if (stompClient != null) {
////            stompClient.disconnect();
////        }
////        isConnected = false;
////        if (listener != null) {
////            listener.onConnectStatusChanged(false);
////        }
////    }
//
//    public void subscribe(String topic) {
//        if (!isConnected) {
//            Log.e(TAG, "无法订阅主题 " + topic + ": WebSocket未连接");
//            return;
//        }
//
//        Log.d(TAG, "订阅主题: " + topic);
//        stompClient.topic(topic).subscribe(topicMessage -> {
//            if (listener != null) {
//                listener.onMessage(topic, topicMessage.getPayload());
//            }
//        }, throwable -> {
//            Log.e(TAG, "订阅主题失败: " + topic, throwable);
//        });
//    }
//}
